/*
	The MIT License

	Copyright (c) 2008 IFMO/GameDev Studio

	Permission is hereby granted, free of charge, to any person obtaining a copy
	of this software and associated documentation files (the "Software"), to deal
	in the Software without restriction, including without limitation the rights
	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
	copies of the Software, and to permit persons to whom the Software is
	furnished to do so, subject to the following conditions:

	The above copyright notice and this permission notice shall be included in
	all copies or substantial portions of the Software.

	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
	THE SOFTWARE.
*/
// shell.h - 


#pragma once


class	EVar : public IVar 
	{
	public:
							EVar			( const char *name, const char *value, uint flags );
		virtual				~EVar			( void );
		
		virtual const char	*Name			( void ) const;
		
		virtual const char	*String			( void ) const { return current_value.c_str(); }
		virtual const char  *Default		( void ) const { return default_value.c_str(); }
		
		virtual void		ResetValue			( void );
		virtual void		SetValue		( const char *val );
		
		virtual int			Int				( void ) const { return val_int; }
		virtual float		Float			( void ) const { return val_float; }
		virtual uint		Flags			( void ) const { return flags; }
		virtual EVec4		Vec4			( void ) const { return val_vec4; }
		virtual EVec3		Vec3			( void ) const { return val_vec3; }
		virtual EVec2		Vec2			( void ) const { return val_vec2; }
		
		void				SetFlags		( uint flags );
		void				ResetFlags		( uint flags );
		void				SetDefault		( const char *def ) { default_value = def; }
		
	private:
		void				Update			( void );
	
		string	name;
		string	current_value;
		string	default_value;
		
		float	val_float;
		int		val_int;
		EVec4	val_vec4;
		EVec3	val_vec3;
		EVec2	val_vec2;
		
		uint	flags;
	};	


struct	ECmdEntry {
		string		name;
		EShellCmd_f	func;
		void		*self;
	};
	
struct	EQueuedCmd {
		EShellCmd_f		func;
		void			*self;
		vector<string>	args;
	};
	
struct EDelayedCmd {
		int		timeout;
		string	command;
	};	
	
class	EShellParser;

class	EShell : public IShell
	{
	public:			
							EShell					( IConsole *con, IFileSystem *fs );
		virtual				~EShell					( void );
										
		virtual	IVar		*RegisterVar			( const char *name, const char *value, uint flags );
		
		virtual void		AddCommand				( const char *name, EShellCmd_f cmd_func, void *self );
		virtual void		RemoveCommand			( const char *name );
						
		virtual void		ExecuteString			( const char *cmd_text );
		virtual void		ExecuteEnqueuedCommands ( void );
		virtual void		ExecuteDelayedCommand	( int delta_time );
		
		virtual void		ExecuteConfig			( const char *file_name );
		virtual void		WriteConfig				( const char *file_name );
		
		virtual const char	*CompleteCommand		( const char *text );

		void				CallCommand				( void );
		void				FlushCmdQueue			( void );
		
	private:
		IVar			*FindVar		( const char *name );
		void			CleanVars		( void );

		IConsole		*con;
		IFileSystem		*fs;
		EShellParser	*parser;
		bool			immediate_mode;
		
				//	Parser stuff :
		vector<string>	parsed_command;
		string			parsed_token;
		void			ParseText		( const char *text );
		bool			ParseComment	( const char *&scan );
		bool			ParseString 	( const char *&scan );
		bool			ParseToken		( const char *&scan );
		
		vector	<EVar*>			var_list;
		vector	<ECmdEntry>		cmd_list;
		vector	<EDelayedCmd>	delayed_cmds;
		
		queue<EQueuedCmd>	cmd_queue;
		bool	defer_cmds;
		
		static	void	ListCmds_f		( EShell *self, int argc, const char **argv );
		static	void	ListVars_f		( EShell *self, int argc, const char **argv );
		static	void	TestArgs_f		( EShell *self, int argc, const char **argv );
		static  void	Wait_f			( EShell *self, int argc, const char **argv );

		static	void	VarCmd_f		( EShell *self, int argc, const char **argv );
		static	void	Set_f			( EShell *self, int argc, const char **argv );
		static	void	Get_f			( EShell *self, int argc, const char **argv );
		static	void	Echo_f			( EShell *self, int argc, const char **argv );
		
		static void		Exec_f			( EShell *self, int argc, const char **argv );
		static void		WriteCfg_f		( EShell *self, int argc, const char **argv );
		
		static	void	Delay_f			( EShell *self, int argc, const char **argv );
	};	
	

